namespace ScrumSprintMonitor.Modules.WorkItemMonitor.ViewModels
{
	#region #using Directives

	using System.Collections.Generic;
	using System.Linq;
	using System.Threading;

	using Infrastructure;

	using Microsoft.Practices.ServiceLocation;

	using UI.Wpf.PostSharp;
	using UI.Wpf.Properties;
	using UI.Wpf.ViewModels;

	#endregion

	[GuardDisposed]
	public class UserStoryCountChartViewModel : SprintChartViewModelBase<IWorkItemCountPieChartData>,
	                                            IUserStoryCountChartViewModel
	{
		static UserStoryCountChartViewModel()
		{
			var dependsOn = Register<UserStoryCountChartViewModel>();

			dependsOn.Call(me =>
			               {
			               	if (me.PieChartData.Any())
			               	{
			               		me.GetUserStoryCountPieChartData(0).Value = me.ReadyForTestWork_UserStoryCount;
			               	}
			               }).OnChanged(me => me.ReadyForTestWork_UserStoryCount);
			dependsOn.Call(me =>
			               {
			               	if (me.PieChartData.Any())
			               	{
			               		me.GetUserStoryCountPieChartData(2).Value = me.ActiveWork_UserStoryCount;
			               	}
			               }).OnChanged(me => me.ActiveWork_UserStoryCount);
			dependsOn.Call(me =>
			               {
			               	if (me.PieChartData.Any())
			               	{
			               		me.GetUserStoryCountPieChartData(3).Value = me.NotDoneWork_UserStoryCount;
			               	}
			               }).OnChanged(me => me.NotDoneWork_UserStoryCount);
		}

		public UserStoryCountChartViewModel(IServiceLocator serviceLocator, ISprintHoursChartViewModel sprintHoursChartViewModel)
			: base(serviceLocator)
		{
			this.sprintHoursChartViewModel = sprintHoursChartViewModel;
		}

		#region Private Fields

		private readonly ISprintHoursChartViewModel sprintHoursChartViewModel;

		#endregion

		#region Private Methods

		protected override void OnSprintDataInitialized()
		{
			if (PieChartData.Count == 4)
			{
				return;
			}

			PieChartData.Clear();

			PieChartData.Add(new WorkItemCountPieChartData
			                 	{
			                 		Value = ReadyForTestWork_UserStoryCount,
			                 		StateName = Resources.WorkItemState_ReadyForTest,
			                 		TimeDimension = this.sprintHoursChartViewModel.PieChartData[0]
			                 	});
			PieChartData.Add(new WorkItemCountPieChartData
			                 	{
			                 		Value = 0.0,
			                 		StateName = string.Empty,
			                 		TimeDimension = this.sprintHoursChartViewModel.PieChartData[1]
			                 	});
			PieChartData.Add(new WorkItemCountPieChartData
			                 	{
			                 		Value = ActiveWork_UserStoryCount,
			                 		StateName = Resources.WorkItemState_Active,
			                 		TimeDimension = this.sprintHoursChartViewModel.PieChartData[2]
			                 	});
			PieChartData.Add(new WorkItemCountPieChartData
			                 	{
			                 		Value = NotDoneWork_UserStoryCount,
			                 		StateName = Resources.WorkItemState_NotDone,
			                 		TimeDimension = this.sprintHoursChartViewModel.PieChartData[3]
			                 	});
		}

		protected override void OnCalculateWorkItemData(IList<IWorkItemAdapter> workItems)
		{
			base.OnCalculateWorkItemData(workItems);

			int readyForTestUserStories = 0, activeUserStories = 0, notDoneUserStories = 0;

			var userStories = workItems.Where(x => x.Type == WorkItemType.UserStory || x.Type == WorkItemType.Defect);
			Parallel.Invoke(() => readyForTestUserStories = userStories.Count(x => x.State == WorkItemState.Done),
			                () => activeUserStories = userStories.Count(x => x.State == WorkItemState.InProgress),
			                () => notDoneUserStories = userStories.Count(x => x.State == WorkItemState.NotDone));

			ReadyForTestWork_UserStoryCount = readyForTestUserStories;
			ActiveWork_UserStoryCount = activeUserStories;
			NotDoneWork_UserStoryCount = notDoneUserStories;
		}

		#endregion

		private IWorkItemCountPieChartData GetUserStoryCountPieChartData(int index)
		{
			return PieChartData[index];
		}

		#region Implementation of IUserStoryCountChartViewModel

		[Notify]
		public int ActiveWork_UserStoryCount { get; private set; }

		[Notify]
		public int ReadyForTestWork_UserStoryCount { get; private set; }

		[Notify]
		public int NotDoneWork_UserStoryCount { get; private set; }

		#endregion

		#region Implementation of ISprintChartViewModel

		public override string Caption
		{
			get { return Resources.ChartCaption_UserStories; }
		}

		#endregion
	}
}